package cn.mujiankeji.mbrowser.功能.广告拦截

import cn.mujiankeji.mbrowser.工具.JSON
import cn.mujiankeji.mbrowser.功能.广告拦截.广告拦截操作.配置文件路径
import cn.mujiankeji.mbrowser.功能.广告拦截.项目.广告拦截订阅文件简介信息
import cn.mujiankeji.mbrowser.功能.广告拦截.项目.规则列表容器
import com.blankj.utilcode.util.FileIOUtils
import com.blankj.utilcode.util.FileUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import java.io.File
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write

class 广告拦截订阅文件助手(val 读写锁:ReentrantReadWriteLock){
    
    /**
     * 获取所有规则订阅信息
     *
     * @return 规则订阅信息列表
     */
    fun 获取所有规则() : List<广告拦截订阅文件简介信息> {
        return 广告拦截操作.读写锁.read {
            try {
                val file = File(配置文件路径)
                if (file.exists()) {
                    val jsonString = FileIOUtils.readFile2String(file)
                    JSON.decodeFromString<规则列表容器>(jsonString).rules
                } else {
                    emptyList()
                }
            } catch (e: Exception) {
                e.printStackTrace()
                emptyList()
            }
        }
    }

    /**
     * 根据ID查找规则订阅信息
     *
     * @param id 规则ID
     * @return 规则订阅信息，如果不存在则返回null
     */
    fun 查找规则(name : String): 广告拦截订阅文件简介信息? {
        return 获取所有规则().find { it.name == name }
    }

    /**
     * 添加规则订阅
     *
     * @param 规则 规则订阅信息
     * @return 添加后的规则ID
     */
    fun 添加规则(规则: 广告拦截订阅文件简介信息) : 广告拦截订阅文件简介信息{
        广告拦截操作.读写锁.write {
            val 规则列表 = 获取所有规则().toMutableList()

            // 生成新ID
            val 原始名称 = 规则.name
            var pos = 1
            if (规则列表.isNotEmpty()) {
                while (规则列表.find { it.name == 规则.name } != null){
                    规则.name = 原始名称 + "(${pos++})"
                }
            }
            规则列表.add(规则)

            // 保存到文件
            保存(规则列表)
        }
        return 规则
    }

    /**
     * 删除规则订阅
     *
     * @param id 要删除的规则ID
     * @return 是否删除成功
     */
    fun 删除规则(name : String): Boolean {
        return 广告拦截操作.读写锁.write {
            val 规则列表 = 获取所有规则().toMutableList()
            val 初始大小 = 规则列表.size

            规则列表.removeIf { it.name == name }

            if (规则列表.size < 初始大小) {
                保存(规则列表)
                true
            } else {
                false
            }
        }
    }

    fun 更新状态(name : String, 停用 : Boolean = false){
        val 规则 = 查找规则(name) ?: return
        规则.stop = 停用
        更新(规则)

        // TODO
        val 订阅列表 = ArrayList<广告拦截订阅文件简介信息>(获取所有规则())
        读写锁.write {
            for (index in 订阅列表.indices) {
                if (订阅列表[index].name == name) {
                    if (停用) {
                        订阅列表.removeAt(index)
                    } else {
                        // 如果是启用规则，需要重新加载
                        订阅列表[index] = 广告拦截订阅文件简介信息(name)
                    }
                    return
                }
            }

            // 如果不在列表中且启用，则添加
            if (!停用) {
                订阅列表.add(广告拦截订阅文件简介信息(name))
                保存(订阅列表)
            }
        }
    }

    /**
     * 更新规则订阅信息
     *
     * @param 规则 要更新的规则订阅信息
     * @return 是否更新成功
     */
    fun 更新(规则: 广告拦截订阅文件简介信息): Boolean {
        return 读写锁.write {
            val 规则列表 = 获取所有规则().toMutableList()
            val 索引 = 规则列表.indexOfFirst { it.name == 规则.name }

            if (索引 != -1) {
                规则列表[索引] = 规则
                保存(规则列表)
                true
            } else {
                false
            }
        }
    }

    /**
     * 将规则列表保存到JSON文件
     *
     * @param 规则列表 要保存的规则列表
     */
    fun 保存(规则列表: List<广告拦截订阅文件简介信息>) {
        try {
            // 确保目录存在
            FileUtils.createOrExistsDir(广告拦截操作.文件夹路径)

            // 使用kotlinx.serialization序列化
            val container = 规则列表容器(规则列表)
            val jsonString = JSON.encodeToString(container)

            // 写入文件
            FileIOUtils.writeFileFromString(广告拦截操作.配置文件路径, jsonString)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}